#pragma once

#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <ctime>

#include <jsoncpp/json/json.h>

#include <charconv>
#include <random>
#include <iomanip>
#include <atomic>

#include "Log.hpp"

namespace MyRpc
{
    using namespace LogArea;
    class JsonTool
    {
    public:
        // 序列化
        static bool Serialize(const Json::Value &val, std::string &body)
        {
            std::stringstream ss;
            // 先构建一个工厂对象
            Json::StreamWriterBuilder swb;

            // 通过工厂类实现派生类对象
            std::shared_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            int ret = sw->write(val, &ss);
            if (ret != 0)
            {
                LogArea::LOG(LogLevel::ERROR) << "Json Serialize error";
                return false;
            }

            // 将序列化的消息带出
            body = ss.str();
            return true;
        }

        // 反序列化
        static bool UnSerialize(const std::string &body, Json::Value &val)
        {
            // 实例化工厂对象
            Json::CharReaderBuilder crb;

            // 通过工厂生产派生类
            std::shared_ptr<Json::CharReader> cr(crb.newCharReader());

            // 获取错误信息
            std::string errs;
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
            if (ret == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "Json UnSerialize error";
                return false;
            }

            return true;
        }
    };

    class UuId
    {
    public:
        std::string Uuid()
        {
            std::stringstream ss;

            // 构造一个机器随机数对象
            std::random_device rd;

            // 以机器随机数为对象构造伪随机数
            std::mt19937 generator(rd());

            // 限定数据范围: 构造限定数据范围的对象
            std::uniform_int_distribution<int> distribution(0, 255);

            // 生成8个随机数, 按照特定格式组织成为16进制数字字符的字符串
            for (int i = 0; i < 8; i++)
            {
                if (i == 4 || i == 6)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
            }

            ss << "-";
            // 定义一个逐渐递增的8字节序号，组织成为16进制数字字符的字符串
            static std::atomic<size_t> seq(1); // 00 00 00 00 00 00 00 01  //8字节
            size_t cur = seq.fetch_add(1);     // 原子++

            for (int i = 7; i >= 0; i--)
            {
                if (i == 5)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i * 8)) & 0xFF);
            }

            return ss.str();
        }
    };
}
